package com.jd.xsl.util;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.jd.dl.util.FileUtil;


public class ExcelUtil {
	
	/**
	 * 根据合并区域重新计算列号
	 * @param row 行
	 * @param column 列号
	 * @return 重新计算的列号
	 */
	public static int getRealColumnIndex(Row row, int column){
		int index = column + getRealColumnOffset(row, column);
		
		if (row.getCell(index) == null){
			return index;
		} else {
			return index + 1;
		}
	}
	
	/**
	 * 根据合并区域计算列的偏移量
	 * @param row 行
	 * @param column 列号
	 * @return 列的偏移量
	 */
	public static int getRealColumnOffset(Row row, int column){
		int offset= 0;
		
		while (isCellInMergedRange(row.getSheet(), row.getRowNum(), column + offset)) {
			offset++;
		} 
		
		return offset;
	}

	/**
	 * 合并单元格
	 * @param sheet 页
	 * @param firstRow 起始行号
	 * @param lastRow 截止行号
	 * @param firstColumn 起始列号
	 * @param lastColumn 截止列号
	 * @return 合并区域的序号
	 */
	public static int addMergedRegion(Sheet sheet, int firstRow, int lastRow, int firstColumn, int lastColumn) {
		return addMergedRegion(sheet, firstRow, lastRow, firstColumn, lastColumn, null);
	}
	
	/**
	 * 合并单元格并设置合并区域的样式
	 * @param sheet 页
	 * @param firstRow 起始行号
	 * @param lastRow 截止行号
	 * @param firstColumn 起始列号
	 * @param lastColumn 截止列号
	 * @param style 样式
	 * @return 合并区域的序号
	 */
	public static int addMergedRegion(Sheet sheet, int firstRow, int lastRow, int firstColumn, int lastColumn, CellStyle style) {
		CellRangeAddress range = new CellRangeAddress(firstRow, lastRow, firstColumn, lastColumn);
		if (style != null){
			setMergedRegionStyle(sheet, range, style);
		}
		return sheet.addMergedRegion(range);
	}

	/**
	 * 创建字体
	 * 
	 * @param wb 工作薄
	 * @param boldweight 粗体
	 * @param color 颜色
	 * @param size 字号
	 * @return 字体
	 */
	public static Font createFont(Workbook wb, short boldweight, short color, short size) {
		Font font = wb.createFont();
		font.setBoldweight(boldweight);
		font.setColor(color);
		font.setFontHeightInPoints(size);
		return font;
	}

	/**
	 * 根据起始行号和列号取得合并单元格的区域
	 * 
	 * @param sheet 页
	 * @param row 合并单元格起始行号
	 * @param column 合并单元格起始列号
	 * @return 合并单元格区域
	 */
	public static CellRangeAddress getMergedRegion(Sheet sheet, int row, int column) {
		for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
			CellRangeAddress region = sheet.getMergedRegion(i);
			if (region.getFirstRow() == row && region.getFirstColumn() == column) {
				return region;
			}
		}
		
		return null;
	}
	
	/**
	 * 
	 * @function 根据行列号得到合并单元格（之前的行列有可能也是合并单元格）
	 * @param sheet
	 * @param row 行号，一个合并单元格算一行
	 * @param column 列号，一个合并单元格算一列
	 * @param rowAdd 是否要加上前几个合并单元格的行号
	 * @param columAdd 是否要加上前几个合并单元格的列号
	 *
	 * @return
	 * @exception
	 *
	 * @author
	 * @history
	 *
	 */
	public static CellRangeAddress getCurrentMergedRegion(Sheet sheet, int row, int column,boolean rowAdd,boolean columAdd){
		for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
			CellRangeAddress region = sheet.getMergedRegion(i);
			if (region.getFirstRow() == row && region.getFirstColumn() == column) {
				return region;
			}else{
				if(rowAdd){
					row = row + (region.getLastRow() - region.getFirstRow());
				}
				if(columAdd){
					column = column + (region.getLastColumn() - region.getFirstColumn());
				}
			}
		}
		
		return null;
	}
	
	/**
	 * 判断是否在合并单元格区域内
	 * @param sheet 页
	 * @param row 行号
	 * @param column 列号
	 * @return 如果行号和列号指定的单元格在合并区域内，返回true；反之，false
	 */
	public static boolean isCellInMergedRange(Sheet sheet, int row, int column){
		for (int i = 0; i < sheet.getNumMergedRegions(); i++) {
			CellRangeAddress region = sheet.getMergedRegion(i);
			if (region.getFirstRow() <= row && row <= region.getLastRow() 
					&& region.getFirstColumn() <= column && column <= region.getLastColumn()) {
				return true;
			}
		}
		
		return false;
	}
	
	/**
	 * 设置合并单元格区域的样式
	 * @param sheet 页
	 * @param region 合并区域
	 * @param style 样式
	 */
	public static void setMergedRegionStyle(Sheet sheet, CellRangeAddress region, CellStyle style) {
		for (int i = region.getFirstRow(); i <= region.getLastRow(); i++) {
			
			Row row = CellUtil.getRow(i, sheet);
			
			for (int j = region.getFirstColumn(); j <= region.getLastColumn(); j++) {
				Cell cell = CellUtil.getCell(row, j);
				cell.setCellStyle(style);
			}
		}
	}
	
	/**
	 * 读取单元格的值
	 * <p><B>注意：</B>如果指定的行或单元格不存在，则自动创建改行</P>
	 * @param sheet 页
	 * @param row 行号
	 * @param column 列号
	 * @return 单元格到值（如果单元格为公式，则以数字形式读取公式的计算结果）
	 */
	public static String getStringCellValue(Sheet sheet, int row, int column) {
		Row r = CellUtil.getRow(row, sheet);;
		Cell cell = CellUtil.getCell(r, column);
		return getStringCellValue(cell);
	}
	
	/**
	 * 读取单元格的值
	 * @param cell 单元格
	 * @return 单元格到值（如果单元格为公式，则以数字形式读取公式的计算结果）
	 */
	public static String getStringCellValue(Cell cell) {
		return getStringCellValue(cell, Cell.CELL_TYPE_NUMERIC);
	}

	/**
	 * 读取单元格的值
	 * @param cell 单元格
	 * @param formulaCellValueType 公式单元格值类型
	 * @return 单元格到值（如果单元格为公式，则以formulaCellValueType形式读取公式的计算结果）
	 */
	public static String getStringCellValue(Cell cell, int formulaCellValueType) {
		switch (cell.getCellType()) {
		case Cell.CELL_TYPE_STRING:
			return cell.getStringCellValue();
		case Cell.CELL_TYPE_NUMERIC:
			String temp = String.valueOf(cell.getNumericCellValue());
			return temp.replaceAll("\\.(0)+$", "");
		case Cell.CELL_TYPE_FORMULA:
			if (Cell.CELL_TYPE_FORMULA == formulaCellValueType){
				return cell.getCellFormula();
			} else {
				cell.setCellType(formulaCellValueType);
				return getStringCellValue(cell);
			}
		case Cell.CELL_TYPE_BLANK:
		case Cell.CELL_TYPE_BOOLEAN:
		case Cell.CELL_TYPE_ERROR:
		default:
			return "";
		}
	}

	/**
	 * 创建虚线边框单元格样式
	 * @param wb 工作薄
	 * @return 虚线边框样式
	 */
	public static CellStyle createDottedBorderCellStyle(Workbook wb) {
		CellStyle style = wb.createCellStyle();
		style.setBorderBottom(CellStyle.BORDER_DOTTED);// 下边框
		style.setBorderLeft(CellStyle.BORDER_DOTTED);// 左边框
		style.setBorderRight(CellStyle.BORDER_DOTTED);// 右边框
		style.setBorderTop(CellStyle.BORDER_DOTTED);// 上边框
		return style;
	}
	
	/**
	 * 创建直线边框单元格样式
	 * @param wb 工作薄
	 * @return 直线边框样式
	 */
	public static CellStyle createThinBorderCellStyle(Workbook wb) {
		CellStyle style = wb.createCellStyle();
		style.setBorderBottom(CellStyle.BORDER_THIN);// 下边框
		style.setBorderLeft(CellStyle.BORDER_THIN);// 左边框
		style.setBorderRight(CellStyle.BORDER_THIN);// 右边框
		style.setBorderTop(CellStyle.BORDER_THIN);// 上边框
		style.setAlignment(CellStyle.ALIGN_CENTER);//水平居中对齐
		style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);//垂直居中对齐
		style.setWrapText(true);//自动换行
		return style;
	}

	public static Workbook getWorkbook(String file) throws FileNotFoundException, IOException{
		Workbook book = null;

		if ("XLS".equalsIgnoreCase(FileUtil.getFileExtension(file))){
			book = new HSSFWorkbook(new FileInputStream(file));
		} else if ("XLSX".equalsIgnoreCase(FileUtil.getFileExtension(file))){
			book = new XSSFWorkbook(new FileInputStream(file));
		}
	
		return book;
	}
}
